package com.sd.jd.jdk_history;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.MultiResolutionImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.ZoneId;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * java9<br/>
 *
 * 1、Java 9 集合工厂方法 {@link Test1} <br/>
 * 2、Java 9 私有接口方法 {@link com.sd.jd.jdk_history.IJd9} <br/>
 * 3、Java 9 改进的进程 API {@link Test3} <br/>
 * 4、Java 9 改进的 Stream API {@link Test4} <br/>
 * 5、Java 9 改进的 try-with-resources {@link Test5} <br/>
 * 6、Java 9 改进的 @Deprecated 注解，用法@Deprecated(since = "1.2", forRemoval = true)
 * <li>since: 元素指定已注解的API元素已被弃用的版本。</li>
 * <li>forRemoval: 元素表示注解的 API 元素在将来的版本中被删除，应该迁移 API。</li> <br/>
 * 7、Java 9 钻石操作符(Diamond Operator) {@link Test7} <br/>
 * 8、Java 9 改进的 Optional 类 {@link Test8} <br/>
 * 9、Java 9 多分辨率图像 API {@link Test9} <br/>
 * 10、Java 9 改进的 CompletableFuture API {@link Test10} <br/>
 */
public class Jd9 {

    public static class Test1 {
        public static void main(String[] args) {
            // 1、集合工厂方法
            // static <E> List<E> of(E e1, E e2, E e3);
            // static <E> Set<E>  of(E e1, E e2, E e3);
            // static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3);
            // static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)

            // List 和 Set 接口, of(...) 方法重载了 0 ~ 10 个参数的不同方法 。
            Set<String> set = Set.of("A", "B", "C");
            System.out.println(set);
            List<String> list = List.of("A", "B", "C");
            System.out.println(list);
            Map<String, String> map = Map.of("A","Apple","B","Boy","C","Cat");
            System.out.println(map);

            Map<String, String> map1 = Map.ofEntries (
                    new AbstractMap.SimpleEntry<>("A","Apple"),
                    new AbstractMap.SimpleEntry<>("B","Boy"),
                    new AbstractMap.SimpleEntry<>("C","Cat"));
            System.out.println(map1);
        }
    }


    /**
     * 在 Java 9 之前，Process API仍然缺乏对使用本地进程的基本支持，例如获取进程的 PID 和所有者，进程的开始时间，进程使用了多少 CPU 时间，多少本地进程正在运行等。
     *
     * Java 9 向 Process API 添加了一个名为 ProcessHandle 的接口来增强 java.lang.Process 类。
     *
     * ProcessHandle 接口的实例标识一个本地进程，它允许查询进程状态并管理进程。
     *
     * ProcessHandle 嵌套接口 Info 来让开发者逃离时常因为要获取一个本地进程的 PID 而不得不使用本地代码的窘境。
     *
     * 我们不能在接口中提供方法实现。如果我们要提供抽象方法和非抽象方法（方法与实现）的组合，那么我们就得使用抽象类。
     *
     * ProcessHandle 接口中声明的 onExit() 方法可用于在某个进程终止时触发某些操作。
     */
    public static class Test3 {
        public static void main(String[] args) throws IOException, InterruptedException {
            ProcessBuilder pb = new ProcessBuilder("notepad.exe");
            String np = "Not Present";
            // 启动windows txt文本编辑器
            Process p = pb.start();
            ProcessHandle.Info info = p.info();
            System.out.printf("Process ID : %s%n", p.pid());
            System.out.printf("Command name : %s%n", info.command().orElse(np));
            System.out.printf("Command line : %s%n", info.commandLine().orElse(np));

            System.out.printf("Start time: %s%n",
                    info.startInstant().map(i -> i.atZone(ZoneId.systemDefault())
                            .toLocalDateTime().toString()).orElse(np));

            System.out.printf("Arguments : %s%n",
                    info.arguments().map(a -> Stream.of(a).collect(
                            Collectors.joining(" "))).orElse(np));

            System.out.printf("User : %s%n", info.user().orElse(np));


        }
    }


    public static class Test4 {
        public static void main(String[] args) {
            // takeWhile() 方法使用一个断言作为参数，返回给定 Stream 的子集直到断言语句第一次返回 false。如果第一个值不满足断言条件，将返回一个空的 Stream。
            // takeWhile() 方法在有序的 Stream 中，takeWhile 返回从开头开始的尽量多的元素；在无序的 Stream 中，takeWhile 返回从开头开始的符合 Predicate 要求的元素的子集。
            Stream.of("a","b","c","","e","f").takeWhile(s->!s.isEmpty())
                    .forEach(s -> {
                        //System.out.println("takeWhile >>>>>>>>>>>> " + s);
                    }); // 输出abc，遇到第一个空就不往后走了，第一次false停止遍历，输出之前为true的集合


            // dropWhile 方法和 takeWhile 作用相反的，使用一个断言作为参数，直到断言语句第一次返回 false 才返回给定 Stream 的子集。
            Stream.of("a","b","c","","e","f","").dropWhile(s-> !s.isEmpty())
                    .forEach(s -> {

                        //System.out.println("dropWhile >>>>>>>>>> " + s);
                    }); // 以上实例 dropWhile 方法在碰到空字符串时开始循环输出，执行输出结果为""ef，遇到第一个false开始输出后面的，第一个为false的数据也会输出


            List<Integer> list = List.of(1, 2, 8, 4, 5, 6, 7);
            List<Integer> takenList = list.stream().dropWhile(number -> number < 5).collect(Collectors.toList());
            // 输出第一个为false，及后面的数据，输出8之后的数据
            //System.out.println(takenList);


            // iterate 方法
            // 方法允许使用初始种子值创建顺序（可能是无限）流，并迭代应用指定的下一个方法。 当指定的 hasNext 的 predicate 返回 false 时，迭代停止。

            // 种子值为3，判断小于10，则每次加3操作
            // int seed 种子值
            // IntPredicate hasNext Predicate是否为true
            // IntUnaryOperator next 一元运算
            {
                IntStream.iterate(3, x -> x < 10, x -> x + 3).forEach(s -> {
                    //System.out.println(s); // 输出 3 6 9
                });
            }

            // ofNullable 方法
            // ofNullable 方法可以预防 NullPointerExceptions 异常， 可以通过检查流来避免 null 值。
            // 如果指定元素为非 null，则获取一个元素并生成单个元素流，元素为 null 则返回一个空流。
            {
                long count = Stream.ofNullable(100).count();
                System.out.println(count);

                count = Stream.ofNullable(null).count();
                System.out.println(count);
            }
        }
    }

    public static class Test5 {
        public static void main(String[] args) throws IOException {
            // 8之前
            // public static void main(String[] args) throws IOException {
            //        System.out.println(readData("test"));
            //    }
            //    static String readData(String message) throws IOException {
            //        Reader inputString = new StringReader(message);
            //        BufferedReader br = new BufferedReader(inputString);
            //        // 这里要把br重新赋值给一个变量，才能用，后续会自动关闭流
            //        try (BufferedReader br1 = br) {
            //            return br1.readLine();
            //        }
            //    }

            System.out.println(readData("test"));

        }

        static String readData(String message) throws IOException {
            Reader inputString = new StringReader(message);
            BufferedReader br = new BufferedReader(inputString);
            try (br) {
                return br.readLine();
            }
        }
    }

    public static class Test7 {
        public static void main(String[] args) throws IOException {

            // 8的写法
            // public class TTT {
            //
            //    public static void main(String[] args) {
            //        // 9之后这块new Handler<Integer>中不需要指定类型了
            //        Handler<Integer> intHandler = new Handler<Integer>(1) {
            //            @Override
            //            public void handle() {
            //                System.out.println(content);
            //            }
            //        };
            //        intHandler.handle();
            //        Handler<? extends Number> intHandler1 = new Handler<Number>(2) {
            //            @Override
            //            public void handle() {
            //                System.out.println(content);
            //            }
            //        };
            //        intHandler1.handle();
            //        Handler<?> handler = new Handler<Object>("test") {
            //            @Override
            //            public void handle() {
            //                System.out.println(content);
            //            }
            //        };
            //        handler.handle();
            //    }
            //}
            //
            //abstract class Handler<T> {
            //    public T content;
            //
            //    public Handler(T content) {
            //        this.content = content;
            //    }
            //
            //    abstract void handle();
            //}
            Handler<Integer> intHandler = new Handler<>(1) {
                @Override
                public void handle() {
                    System.out.println(content);
                }
            };
            intHandler.handle();
            Handler<? extends Number> intHandler1 = new Handler<>(2) {
                @Override
                public void handle() {
                    System.out.println(content);
                }
            };
            intHandler1.handle();
            Handler<?> handler = new Handler<>("test") {
                @Override
                public void handle() {
                    System.out.println(content);
                }
            };

            handler.handle();

        }


    }

    public static class Test8 {
        public static void main(String[] args) {
            List<Optional<String>> list = Arrays.asList(
                    Optional.empty(),
                    Optional.of("A"),
                    Optional.empty(),
                    Optional.of("B")
            );

            // Optional 类
            // 添加了 3 个改进的方法
            // 1、stream() 如果值存在，返回值的 Stream，否则返回 empty Stream，不用像8一样还得判断是否有效，返回空Stream了
            {
                // java 8
                List<String> listJava8 = list.stream()
                        .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
                        .collect(Collectors.toList());
                System.out.println(listJava8);

                // java 9
                List<String> listJava9 = list.stream()
                        .flatMap(Optional::stream)
                        .collect(Collectors.toList());
                System.out.println(listJava9);
            }

            // 2、ifPresentOrElse() 如果值存在，执行包含值得给定操作，否则执行基于 empty 的操作
            {
                Optional<Integer> optional = Optional.of(1);
                optional.ifPresentOrElse(
                        x -> System.out.println("Value: " + x),
                        () -> System.out.println("Not Present.")
                );

                optional = Optional.empty();
                optional.ifPresentOrElse(
                        x -> System.out.println("Value: " + x),
                        () -> System.out.println("Not Present.")
                );
            }

            // 3、or() 如果值存在，返回该值的 Optional，否则返回给定值的 Optional
            {
                Optional<String> optional = Optional.of("Mahesh");
                optional = optional.or(() -> Optional.of("Not Present"));
                optional.ifPresent(x -> System.out.println("Value: " + x));

                optional = Optional.empty();
                optional = optional.or(() -> Optional.of("Not Present"));
                optional.ifPresent(x -> System.out.println("Value: " + x));
            }
        }
    }

    public static class Test9 {
        // 没测试成功，不知道是否可用
        public static void main(String[] args) throws IOException, MalformedURLException {

            List<String> imgUrls = List.of("http://www.runoob.com/wp-content/themes/runoob/assets/img/runoob-logo@2x.png",
                    "http://www.runoob.com/wp-content/themes/runoob/assets/img/runoob-logo.png",
                    "http://www.runoob.com/wp-content/themes/runoob/assets/images/qrcode.png");

            List<Image> images = new ArrayList<>();

            for (String url : imgUrls) {
                images.add(ImageIO.read(new URL(url)));
            }

            // 读取所有图片
            MultiResolutionImage multiResolutionImage =
                    new BaseMultiResolutionImage(images.toArray(new Image[0]));

            // 获取图片的所有分辨率
            List<Image> variants = multiResolutionImage.getResolutionVariants();

            System.out.println("Total number of images: " + variants.size());

            for (Image img : variants) {
                System.out.println(img);
            }

            // 根据不同尺寸获取对应的图像分辨率
            Image variant1 = multiResolutionImage.getResolutionVariant(156, 45);
            System.out.printf("\nImage for destination[%d,%d]: [%d,%d]",
                    156, 45, variant1.getWidth(null), variant1.getHeight(null));

            Image variant2 = multiResolutionImage.getResolutionVariant(311, 89);
            System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 311, 89,
                    variant2.getWidth(null), variant2.getHeight(null));

            Image variant3 = multiResolutionImage.getResolutionVariant(622, 178);
            System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 622, 178,
                    variant3.getWidth(null), variant3.getHeight(null));

            Image variant4 = multiResolutionImage.getResolutionVariant(300, 300);
            System.out.printf("\nImage for destination[%d,%d]: [%d,%d]", 300, 300,
                    variant4.getWidth(null), variant4.getHeight(null));
        }
    }

    public static class Test10 {
        // Java 8 引入了 CompletableFuture<T> 类，可能是 java.util.concurrent.Future<T> 明确的完成版（设置了它的值和状态），也可能被用作java.util.concurrent.CompleteStage 。
        // 支持 future 完成时触发一些依赖的函数和动作。Java 9 引入了一些CompletableFuture 的改进：
        //
        // 支持 delays 和 timeouts
        // 提升了对子类化的支持
        // 新的工厂方法

        // 待补充 TODO....

        public static void main(String[] args) {

        }
    }

}

abstract class Handler<T> {
    public T content;

    public Handler(T content) {
        this.content = content;
    }

    abstract void handle();
}
